{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "感知机 A（perceptron）这一算法。感知机是由美国学者Frank Rosenblatt在1957年提出来的。   \n",
    "感知机也是作为神经网络（深度学习）的起源的算法。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.1、感知机是什么？"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "感知机接收多个输入信号，输出一个信号。  \n",
    "和实际的电流不同的是，感知机的信号只有“流/不流”（1/0）两种取值。  \n",
    "在本书中，0对应“不传递信号”， 1对应“传递信号”。  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "图2-1是一个接收两个输入信号的感知机的例子。 x1、 x2是`输入信号`，\n",
    "y是`输出信号`， w1、 w2是`权重`（w是weight的首字母）。图中的○称为`神经元`或者`节点`。  \n",
    "<img src=\"./imgs/2_1_perceptron.png\"><imgs>  \n",
    "输入信号被送往神经元时，会被分别乘以固定的权重（w1x1、 w2x2）。  \n",
    "神经元会计算传送过来的信号的总和，只有当这个总和超过了某个界限值时，才会输出1。这也称为`神经元被激活`。这里将这个界限值称为`阈值`，用符号θ表示。  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "y = \\left\\{ \\begin{array} { l l } { 0 } & { \\left( w _ { 1 } x _ { 1 } + w _ { 2 } x _ { 2 } \\leqslant \\theta \\right) } \\\\ { 1 } & { \\left( w _ { 1 } x _ { 1 } + w _ { 2 } x _ { 2 } > \\theta \\right) } \\end{array} \\right.\n",
    "$$  \n",
    "<center>式（2.1）</center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "感知机的多个输入信号都有各自固有的权重，这些权重发挥着控制各个信号的重要性的作用。  \n",
    "也就是说，权重越大，对应该权重的信号的重要性就越高。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2、简单的逻辑电路"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2.1、与门（AND gate）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"./imgs/2_2.png\"></img>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "用感知机来表示这个与门，比如，当(w1, w2, θ) = (0.5, 0.5, 0.7) 时，可以满足图 2-2 的条件"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2.2、与非门（NAND gate）和或门（OR gate）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.3、感知机的实现"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3.1、简单实现"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from IPython.core.interactiveshell import InteractiveShell\n",
    "InteractiveShell.ast_node_interactivity = \"all\"\n",
    "import numpy as np\n",
    "def AND(x1, x2):\n",
    "    w1, w2, theta = 0.5, 0.5, 0.7\n",
    "    tmp = x1*w1 + x2*w2\n",
    "    if tmp <= theta:\n",
    "        return 0\n",
    "    elif tmp > theta:\n",
    "        return 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "AND(0,0)\n",
    "AND(1,0)\n",
    "AND(0,1)\n",
    "AND(1,1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def NAND(x1, x2):\n",
    "    x = np.array([x1, x2])\n",
    "    w = np.array([-0.5, -0.5]) # 仅权重和偏置与AND不同！\n",
    "    b = 0.7\n",
    "    tmp = np.sum(w*x) + b\n",
    "    if tmp <= 0:\n",
    "        return 0\n",
    "    else:\n",
    "        return 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def OR(x1, x2):\n",
    "    x = np.array([x1, x2])\n",
    "    w = np.array([0.5, 0.5]) # 仅权重和偏置与AND不同！\n",
    "    b = -0.2\n",
    "    tmp = np.sum(w*x) + b\n",
    "    if tmp <= 0:\n",
    "        return 0\n",
    "    else:\n",
    "        return 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3.2 导入权重和偏置"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "刚才的与门的实现比较直接、容易理解，但是考虑到以后的事情，我们将其修改为另外一种实现形式。  \n",
    "在此之前，首先把式（2.1）的θ换成−b，于是就可以用式（2.2）来表示感知机的行为。\n",
    "$$\n",
    "y = \\left\\{ \\begin{array} { l l } { 0 } & { \\left( b + w _ { 1 } x _ { 1 } + w _ { 2 } x _ { 2 } \\leqslant 0 \\right) } \\\\ { 1 } & { \\left( b + w _ { 1 } x _ { 1 } + w _ { 2 } x _ { 2 } > 0 \\right) } \\end{array} \\right.\n",
    "$$  \n",
    "<center>式（2.2）</center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.4、感知机的局限性"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.4.1、异或门"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "异或门也被称为逻辑异或电路。\n",
    "仅当x1或x2中的一方为1时，才会输出1（“异或”是拒绝其他的意思）。  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "y = \\left\\{ \\begin{array} { l l } { 0 } & { \\left( - 0.5 + x _ { 1 } + x _ { 2 } \\leqslant 0 \\right) } \\\\ { 1 } & { \\left( - 0.5 + x _ { 1 } + x _ { 2 } > 0 \\right) } \\end{array} \\right.\n",
    "$$ <center>式(2.3)</center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "式（2.3）表示的感知机会生成由直线−0.5 + x1 + x2 = 0分割开的两个空\n",
    "间。其中一个空间输出1，另一个空间输出0，如图2-6所示<img src=\"./imgs/2_6.png\"></imgs>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.4.2、线性和非线性"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "感知机的局限性就在于它只能表示由一条直线分割的空间。  \n",
    "图2-8这样弯曲的曲线无法用感知机表示。  \n",
    "另外，由图2-8这样的曲线分割而成的空间称为非线性空间，由直线分割而成的空间称为线性空间。  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"./imgs/2_8.png\"></imgs>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.5、多层感知机"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "感知机的绝妙之处在于它可以“叠加层”（通过叠加层来表示异或门是本节的要点）。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.5.1、已有门电路的组合"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "异或门的制作方法有很多，其中之一就是组合我们前面做好的与门、与\n",
    "非门、或门进行配置。这里，与门、与非门、或门用图2-9中的符号表示。另外，\n",
    "图2-9中与非门前端的○表示反转输出的意思。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"./imgs/2_9_2_10.png\"></imgs>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "异或门可以通过图2-11所示的配置来实现。  \n",
    "这里， x1和x2表示输入信号，y表示输出信号。 x1和x2是与非门和或门的输入，而与非门和或门的输出则是与门的输入。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"./imgs/2_11.png\"></imgs>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.5.2、异或门的实现"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def XOR(x1, x2):\n",
    "    s1 = NAND(x1, x2)\n",
    "    s2 = OR(x1, x2)\n",
    "    y = AND(s1, s2)\n",
    "    return y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "XOR(0, 0) # 输出0\n",
    "XOR(1, 0) # 输出1\n",
    "XOR(0, 1) # 输出1\n",
    "XOR(1, 1) # 输出0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "下面我们试着用感知机的表示方法（明确地显示神经元）来表示这个异或门，结果如图2-13所示。  \n",
    "如图2-13所示，异或门是一种多层结构的神经网络。这里，将最左边的\n",
    "一列称为第0层，中间的一列称为第1层，最右边的一列称为第2层。  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "图2-13所示的感知机与前面介绍的与门、或门的感知机（图2-1）形状不\n",
    "同。  \n",
    "实际上，与门、或门是单层感知机，而异或门是2层感知机。  \n",
    "叠加了多层的感知机也称为多层感知机（multi-layered perceptron）。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"./imgs/2_13.png\"></img>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "图2-13中的感知机总共由3层构成，但是因为拥有权重的层实质上只有2层（第0层和第1层之间，第1层和第2层之间），所以称为“2层感知机”。  \n",
    "不过，有的文献认为图2-13的感知机是由3层构成的，因而将其称为“3层感知机”。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在图2-13所示的2层感知机中，先在第0层和第1层的神经元之间进行\n",
    "信号的传送和接收，然后在第1层和第2层之间进行信号的传送和接收，具\n",
    "体如下所示：  \n",
    "1.第0层的两个神经元接收输入信号，并将信号发送至第1层的神经元。  \n",
    "2.第1层的神经元将信号发送至第2层的神经元，第2层的神经元输出y。   "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这种2层感知机的运行过程可以比作流水线的组装作业。  \n",
    "第1段（第1层）的工人对传送过来的零件进行加工，完成后再传送给第2段（第2层）的工人。  \n",
    "第2层的工人对第1层的工人传过来的零件进行加工，完成这个零件后出货（输出）。  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "像这样，在异或门的感知机中，工人之间不断进行零件的传送。通过这样的结构（2层结构），感知机得以实现异或门。  \n",
    "这可以解释为“单层感知机无法表示的东西，通过增加一层就可以解决”。  \n",
    "也就是说，通过叠加层（加深层），感知机能进行更加灵活的表示"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.6、从与非门到计算机"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.7、小结"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "'''\n",
    "1、感知机是具有输入和输出的算法。给定一个输入后，将输出一个既\n",
    "定的值。\n",
    "2、感知机将权重和偏置设定为参数。\n",
    "3、使用感知机可以表示与门和或门等逻辑电路。\n",
    "4、异或门无法通过单层感知机来表示。\n",
    "5、使用2层感知机可以表示异或门。\n",
    "6、单层感知机只能表示线性空间，而多层感知机可以表示非线性空间。\n",
    "7、多层感知机（在理论上）可以表示计算机\n",
    "'''"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
